/**
 * Copyright (c) www.longdw.com
 */
package com.ldw.music.lrc;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.annotation.SuppressLint;
import android.util.Log;

import com.ldw.music.model.LyricSentence;

/**
 * 姝岃瘝鐨勬樉绀烘帶鍒� * @author longdw(longdawei1988@gmail.com)
 *
 */
public class LyricLoadHelper {
	/** 鐢ㄤ簬鍚戝閫氱煡姝岃瘝杞藉叆銆佸彉鍖栫殑鐩戝惉鍣�*/
	public interface LyricListener {

		/**
		 * 姝岃瘝杞藉叆鏃惰皟鐢�		 * 
		 * @param lyricSentences
		 *            姝岃瘝鏂囨湰澶勭悊鍚庣殑鎵�湁姝岃瘝鍙ュ瓙
		 * @param indexOfCurSentence
		 *            姝ｅ湪鎾斁鐨勫彞瀛愬湪鍙ュ瓙闆嗗悎涓殑绱㈠紩鍙�		 */
		public abstract void onLyricLoaded(List<LyricSentence> lyricSentences,
				int indexOfCurSentence);

		/**
		 * 姝岃瘝鍙樺寲鏃惰皟鐢�		 * 
		 * @param indexOfCurSentence
		 *            姝ｅ湪鎾斁鐨勫彞瀛愬湪鍙ュ瓙闆嗗悎涓殑绱㈠紩鍙�		 * @param currentTime
		 *            宸茬粡鎾斁鐨勬绉掓暟
		 * */
		public abstract void onLyricSentenceChanged(int indexOfCurSentence);
	}

	private static final String TAG = LyricLoadHelper.class.getSimpleName();

	/** 鍙ュ瓙闆嗗悎 */
	private ArrayList<LyricSentence> mLyricSentences = new ArrayList<LyricSentence>();

	private LyricListener mLyricListener = null;

	private boolean mHasLyric = false;

	/** 褰撳墠姝ｅ湪鎾斁鐨勬瓕璇嶅彞瀛愮殑鍦ㄥ彞瀛愰泦鍚堜腑鐨勭储寮曞彿 */
	private int mIndexOfCurrentSentence = -1;

	/** 鐢ㄤ簬缂撳瓨鐨勪竴涓鍒欒〃杈惧紡瀵硅薄,璇嗗埆[]涓殑鍐呭锛屼笉鍖呮嫭涓嫭鍙�*/
	private final Pattern mBracketPattern = Pattern
			.compile("(?<=\\[).*?(?=\\])");
	private final Pattern mTimePattern = Pattern
			.compile("(?<=\\[)(\\d{2}:\\d{2}\\.?\\d{0,3})(?=\\])");

	private final String mEncoding = "utf-8";

	public List<LyricSentence> getLyricSentences() {
		return mLyricSentences;
	}

	public void setLyricListener(LyricListener listener) {
		this.mLyricListener = listener;
	}

	public void setIndexOfCurrentSentence(int index) {
		mIndexOfCurrentSentence = index;
	}

	public int getIndexOfCurrentSentence() {
		return mIndexOfCurrentSentence;
	}

	/**
	 * 鏍规嵁姝岃瘝鏂囦欢鐨勮矾寰勶紝璇诲彇鍑烘瓕璇嶆枃鏈苟瑙ｆ瀽
	 * 
	 * @param lyricPath
	 *            姝岃瘝鏂囦欢璺緞
	 * @return true琛ㄧず瀛樺湪姝岃瘝锛宖alse琛ㄧず涓嶅瓨鍦ㄦ瓕璇�	 */
	public boolean loadLyric(String lyricPath) {
		Log.i(TAG, "LoadLyric begin,path is:" + lyricPath);
		mHasLyric = false;
		mLyricSentences.clear();

		if (lyricPath != null) {
			File file = new File(lyricPath);
			if (file.exists()) {
				Log.i(TAG, "姝岃瘝鏂囦欢瀛樺湪");
				mHasLyric = true;
				try {
					FileInputStream fr = new FileInputStream(file);
					InputStreamReader isr = new InputStreamReader(fr, mEncoding);
					BufferedReader br = new BufferedReader(isr);

					String line = null;

					// 閫愯鍒嗘瀽姝岃瘝鏂囨湰
					while ((line = br.readLine()) != null) {
						Log.i(TAG, "lyric line:" + line);
						parseLine(line);
					}

					// 鎸夋椂闂存帓搴忓彞瀛愰泦鍚�					Collections.sort(mLyricSentences,
							new Comparator<LyricSentence>() {
								// 鍐呭祵锛屽尶鍚嶇殑compare绫�								public int compare(LyricSentence object1,
										LyricSentence object2) {
									if (object1.getStartTime() > object2
											.getStartTime()) {
										return 1;
									} else if (object1.getStartTime() < object2
											.getStartTime()) {
										return -1;
									} else {
										return 0;
									}
								}
							});

					for (int i = 0; i < mLyricSentences.size() - 1; i++) {
						mLyricSentences.get(i).setDuringTime(
								mLyricSentences.get(i + 1).getStartTime());
					}
					mLyricSentences.get(mLyricSentences.size() - 1)
							.setDuringTime(Integer.MAX_VALUE);
					fr.close();
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
				}
			} else {
				Log.i(TAG, "姝岃瘝鏂囦欢涓嶅瓨鍦�);
			}
		}
		// 濡傛灉鏈夎皝鍦ㄧ洃鍚紝閫氱煡瀹冩瓕璇嶈浇鍏ュ畬鍟︼紝骞舵妸杞藉叆鐨勫彞瀛愰泦鍚堜篃浼犻�杩囧幓
		if (mLyricListener != null) {
			mLyricListener.onLyricLoaded(mLyricSentences,
					mIndexOfCurrentSentence);
		}
		if (mHasLyric) {
			Log.i(TAG, "Lyric file existed.Lyric has " + mLyricSentences.size()
					+ " Sentences");
		} else {
			Log.i(TAG, "Lyric file does not existed");
		}
		return mHasLyric;
	}

	/**
	 * 鏍规嵁浼犻�杩囨潵鐨勫凡鎾斁鐨勬绉掓暟锛岃绠楀簲褰撳搴斿埌鍙ュ瓙闆嗗悎涓殑鍝竴鍙ワ紝鍐嶉�鐭ョ洃鍚�鎾斁鍒扮殑浣嶇疆銆�	 * 
	 * @param millisecond
	 *            宸叉挱鏀剧殑姣鏁�	 */
	public void notifyTime(long millisecond) {
		// Log.i(TAG, "notifyTime");
		if (mHasLyric && mLyricSentences != null && mLyricSentences.size() != 0) {
			int newLyricIndex = seekSentenceIndex(millisecond);
			if (newLyricIndex != -1 && newLyricIndex != mIndexOfCurrentSentence) {// 濡傛灉鎵惧埌鐨勬瓕璇嶅拰鐜板湪鐨勪笉鏄竴鍙ャ�
				if (mLyricListener != null) {
					// 鍛婅瘔涓�０锛屾瓕璇嶅凡缁忓彉鎴愬彟澶栦竴鍙ュ暒锛�					mLyricListener.onLyricSentenceChanged(newLyricIndex);
				}
				mIndexOfCurrentSentence = newLyricIndex;
			}
		}
	}

	private int seekSentenceIndex(long millisecond) {
		int findStart = 0;
		if (mIndexOfCurrentSentence >= 0) {
			// 濡傛灉宸茬粡鎸囧畾浜嗘瓕璇嶏紝鍒欑幇鍦ㄤ綅缃紑濮�			findStart = mIndexOfCurrentSentence;
		}

		try {
			long lyricTime = mLyricSentences.get(findStart).getStartTime();

			if (millisecond > lyricTime) { // 濡傛灉鎯宠鏌ユ壘鐨勬椂闂村湪鐜板湪瀛楀箷鐨勬椂闂翠箣鍚�				// 濡傛灉寮�浣嶇疆缁忔槸鏈�悗涓�彞浜嗭紝鐩存帴杩斿洖鏈�悗涓�彞銆�				if (findStart == (mLyricSentences.size() - 1)) {
					return findStart;
				}
				int new_index = findStart + 1;
				// 鎵惧埌绗竴鍙ュ紑濮嬫椂闂村ぇ浜庤緭鍏ユ椂闂寸殑姝岃瘝
				while (new_index < mLyricSentences.size()
						&& mLyricSentences.get(new_index).getStartTime() <= millisecond) {
					++new_index;
				}
				// 杩欏彞姝岃瘝鐨勫墠涓�彞灏辨槸鎴戜滑瑕佹壘鐨勪簡銆�				return new_index - 1;
			} else if (millisecond < lyricTime) { // 濡傛灉鎯宠鏌ユ壘鐨勬椂闂村湪鐜板湪瀛楀箷鐨勬椂闂翠箣鍓�				// 濡傛灉寮�浣嶇疆缁忔槸绗竴鍙ヤ簡锛岀洿鎺ヨ繑鍥炵涓�彞銆�				if (findStart == 0)
					return 0;

				int new_index = findStart - 1;
				// 鎵惧埌寮�鏃堕棿灏忎簬杈撳叆鏃堕棿鐨勬瓕璇�				while (new_index > 0
						&& mLyricSentences.get(new_index).getStartTime() > millisecond) {
					--new_index;
				}
				// 灏辨槸瀹冧簡銆�				return new_index;
			} else {
				// 涓嶇敤鎵句簡
				return findStart;
			}
		} catch (IndexOutOfBoundsException e) {
			e.printStackTrace();
			Log.i(TAG, "鏂扮殑姝岃瘝杞藉叆浜嗭紝鎵�互浜х敓浜嗚秺鐣岄敊璇紝涓嶇敤鐞嗕細锛岃繑鍥�");
			return 0;
		}
	}

	/** 瑙ｆ瀽姣忚姝岃瘝鏂囨湰,涓�鏂囨湰姝岃瘝鍙兘瀵瑰簲澶氫釜鏃堕棿鎴�*/
	private void parseLine(String line) {
		if (line.equals("")) {
			return;
		}
		String content = null;
		int timeLength = 0;
		int index = 0;
		Matcher matcher = mTimePattern.matcher(line);
		int lastIndex = -1;// 鏈�悗涓�釜鏃堕棿鏍囩鐨勪笅鏍�		int lastLength = -1;// 鏈�悗涓�釜鏃堕棿鏍囩鐨勯暱搴�
		// 涓�鏂囨湰姝岃瘝鍙兘瀵瑰簲澶氫釜鏃堕棿鎴筹紝濡傗�[01:02.3][01:11:22.33]鍦ㄨ繖闃冲厜鏄庡獨鐨勬槬澶╅噷鈥�		// 涓�涔熷彲鑳藉寘鍚涓彞瀛愶紝濡傗�[01:02.3]鍦ㄨ繖闃冲厜鏄庡獨鐨勬槬澶╅噷[01:02:22.33]鎴戠殑鐪兼唱蹇嶄笉浣忔祦娣屸�
		List<String> times = new ArrayList<String>();

		// 瀵绘壘鍑烘湰琛屾墍鏈夋椂闂存埑锛屽瓨鍏imes涓�		while (matcher.find()) {
			// 鍖归厤鐨勬槸涓嫭鍙烽噷鐨勫瓧绗︿覆锛屽01:02.3锛�1:11:22.33

			String s = matcher.group();
			index = line.indexOf("[" + s + "]");
			if (lastIndex != -1 && index - lastIndex > lastLength + 2) {
				// 濡傛灉澶т簬涓婃鐨勫ぇ灏忥紝鍒欎腑闂村す浜嗗埆鐨勫唴瀹瑰湪閲岄潰
				// 杩欎釜鏃跺�灏辫鍒嗘浜�				content = trimBracket(line.substring(
						lastIndex + lastLength + 2, index));
				for (String string : times) {
					// 灏嗘瘡涓椂闂存埑瀵瑰簲鐨勪竴浠藉彞瀛愬瓨鍏ュ彞瀛愰泦鍚�					long t = parseTime(string);
					if (t != -1) {
						Log.i(TAG, "line content match-->" + content);
						mLyricSentences.add(new LyricSentence(t, content));
					}
				}
				times.clear();
			}
			times.add(s);
			lastIndex = index;
			lastLength = s.length();

			Log.i(TAG, "time match--->" + s);
		}
		// 濡傛灉鍒楄〃涓虹┖锛屽垯琛ㄧず鏈娌℃湁鍒嗘瀽鍑轰换浣曟爣绛�		if (times.isEmpty()) {
			return;
		}

		timeLength = lastLength + 2 + lastIndex;
		if (timeLength > line.length()) {
			content = trimBracket(line.substring(line.length()));
		} else {
			content = trimBracket(line.substring(timeLength));
		}
		Log.i(TAG, "line content match-->" + content);
		// 灏嗘瘡涓椂闂存埑瀵瑰簲鐨勪竴浠藉彞瀛愬瓨鍏ュ彞瀛愰泦鍚�		for (String s : times) {
			long t = parseTime(s);
			if (t != -1) {
				mLyricSentences.add(new LyricSentence(t, content));
			}
		}
	}

	/** 鍘婚櫎鎸囧畾瀛楃涓蹭腑鍖呭惈[XXX]褰㈠紡鐨勫瓧绗︿覆 */
	private String trimBracket(String content) {
		String s = null;
		String result = content;
		Matcher matcher = mBracketPattern.matcher(content);
		while (matcher.find()) {
			s = matcher.group();
			result = result.replace("[" + s + "]", "");
		}
		return result;
	}

	/** 灏嗘瓕璇嶇殑鏃堕棿瀛楃涓茶浆鍖栨垚姣鏁帮紝濡傛灉鍙傛暟鏄�0:01:23.45 */
	@SuppressLint("DefaultLocale")
	private long parseTime(String strTime) {
		String beforeDot = new String("00:00:00");
		String afterDot = new String("0");

		// 灏嗗瓧绗︿覆鎸夊皬鏁扮偣鎷嗗垎鎴愭暣绉掗儴鍒嗗拰灏忔暟閮ㄥ垎銆�		int dotIndex = strTime.indexOf(".");
		if (dotIndex < 0) {
			beforeDot = strTime;
		} else if (dotIndex == 0) {
			afterDot = strTime.substring(1);
		} else {
			beforeDot = strTime.substring(0, dotIndex);// 00:01:23
			afterDot = strTime.substring(dotIndex + 1); // 45
		}

		long intSeconds = 0;
		int counter = 0;
		while (beforeDot.length() > 0) {
			int colonPos = beforeDot.indexOf(":");
			try {
				if (colonPos > 0) {// 鎵惧埌鍐掑彿浜嗐�
					intSeconds *= 60;
					intSeconds += Integer.valueOf(beforeDot.substring(0,
							colonPos));
					beforeDot = beforeDot.substring(colonPos + 1);
				} else if (colonPos < 0) {// 娌℃壘鍒帮紝鍓╀笅閮藉綋涓�釜鏁板鐞嗕簡銆�					intSeconds *= 60;
					intSeconds += Integer.valueOf(beforeDot);
					beforeDot = "";
				} else {// 绗竴涓氨鏄啋鍙凤紝涓嶅彲鑳斤紒
					return -1;
				}
			} catch (NumberFormatException e) {
				return -1;
			}
			++counter;
			if (counter > 3) {// 涓嶄細瓒呰繃灏忔椂锛屽垎锛岀鍚с�
				return -1;
			}
		}
		// intSeconds=83

		String totalTime = String.format("%d.%s", intSeconds, afterDot);// totaoTimer
		// =
		// "83.45"
		Double doubleSeconds = Double.valueOf(totalTime); // 杞垚灏忔暟83.45
		return (long) (doubleSeconds * 1000);// 杞垚姣8345
	}

}